package com.seeyon.apps.lzmzj.util;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.datamatrix.encoder.SymbolShapeHint;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @description: 二维码工具类
 **/
public class QRCodeUtil {

    //黑色
    private static final int BLACK = 0xFF000000;
    //白色
    private static final int WHITE = 0xFFFFFFFF;
    //编码集
    private static final String CHARSET = "UTF-8";


    /**
     * 创建二维码图片
     *
     * @param content    二维码包含的内容
     * @param width      二维码图片的宽度
     * @param height     二维码图片的高度
     * @param fileName   二维码图片的文件名
     * @param imageType  图片类型（例如PNG, JPEG等）
     * @param filePath   图片存储的路径
     * @return 返回存储路径加文件名的字符串，如果生成失败返回空字符串
     */
    public static String createImage(String content, int width, int height, String fileName, String imageType, String filePath) {
        // 创建一个多种格式的二维码写入器
        MultiFormatWriter multiFormatWriter = new MultiFormatWriter();

        // 初始化编码配置参数
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);// 设置字符编码集
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);// 设置容错率
        hints.put(EncodeHintType.DATA_MATRIX_SHAPE, SymbolShapeHint.FORCE_SQUARE);// 设置数据矩阵的形状

        try {
            // 根据配置参数生成二维码的比特矩阵
            BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hints);

            // 创建文件对象，用于存储二维码图片
            File file = new File(filePath, fileName + "." + imageType);

            // 移除比特矩阵的白边
            bitMatrix = deleteWhite(bitMatrix);

            // 将比特矩阵写入到文件中
            writeToFile(bitMatrix, imageType, file);

            // 返回二维码图片的完整路径
            return filePath + File.separator + fileName + "." + imageType;
        } catch (WriterException | IOException e) {
            // 捕获异常并打印堆栈跟踪信息
            e.printStackTrace();
        }

        // 如果生成失败，返回空字符串
        return "";
    }


    /**
     * 删除BitMatrix中的空白区域
     * 此方法用于移除二维码矩阵外部的空白边框，确保二维码没有多余的空白区域
     *
     * @param matrix 原始的BitMatrix对象，包含二维码数据
     * @return 返回一个新的BitMatrix对象，其中包含原始矩阵中去除空白边框后的二维码数据
     */
    public static BitMatrix deleteWhite(BitMatrix matrix) {
        // 获取二维码矩阵的外接矩形，即包含所有黑色像素点的最小矩形
        int[] rec = matrix.getEnclosingRectangle();
        // 计算结果矩阵的宽度和高度
        int resWidth = rec[2];
        int resHeight = rec[3];
        // 创建一个新的BitMatrix对象，尺寸为计算出的宽度和高度
        BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
        // 清空新矩阵，确保所有像素都设置为白色（默认值）
        resMatrix.clear();
        // 遍历新矩阵的每个像素点
        for (int i = 0; i < resWidth; i++) {
            for (int j = 0; j < resHeight; j++) {
                // 如果原始矩阵中对应的像素点是黑色，则将新矩阵中对应的像素点也设置为黑色
                if (matrix.get(i + rec[0], j + rec[1]))
                    resMatrix.set(i, j);
            }
        }
        // 返回处理后的新矩阵
        return resMatrix;
    }


    /**
     * 将BitMatrix对象转换为图像并写入文件
     * 此方法主要用于将二维矩阵（例如二维码）转换为图像文件，以便于存储和传输
     *
     * @param matrix BitMatrix对象，包含要转换为图像的二维矩阵数据
     * @param format 图像格式，例如"png"、"jpg"等
     * @param file 要写入的文件对象，包括文件路径和名称
     * @throws IOException 如果图像写入文件失败，抛出IOException
     */
    public static void writeToFile(BitMatrix matrix, String format, File file) throws IOException {
        // 获取矩阵的宽度和高度，用于创建图像
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        // 创建一个BufferedImage对象，用于存储转换后的图像数据
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        // 遍历矩阵中的每个点，将其转换为图像中的像素
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                // 根据矩阵点的值设置像素颜色，true设置为黑色，false设置为白色
                image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
            }
        }

        // 将图像写入文件，如果写入失败，则抛出异常
        if (!ImageIO.write(image, format, file)) {
            throw new IOException("Could not write an image of format " + format + " to " + file);
        }
    }

    public static void main(String[] args) {
        //二维码的内容
        String qrCodeContent = "1233";
        System.out.println("二维码的内容：" + qrCodeContent);
        //二维码要生成的路径
        String qrCodeImagePath = "D:/资料";
        //生成Alian.png的二维码图片(去除白边)
        String qrCodeUrl = QRCodeUtil.createImage(qrCodeContent, 300, 300, "qrCode_Alian", "png", qrCodeImagePath);
        System.out.println("生成的二维码地址：" + qrCodeUrl);

        //本地背景图片地址
        String backGroundUrl = "C:\\myFile\\CSDN\\background.png";
        System.out.println("背景图片地址：" + backGroundUrl);
        //最终合成图片的地址
        String imageName = "C:\\myFile\\CSDN\\result.png";
        //图片上的标签绘制
        String title = "嘉禾嘉宁PaPa";
        System.out.println("要添加的文字信息：" + title);
        //合成图片
        ImageUtil.merge(backGroundUrl, qrCodeUrl, imageName, title);
        System.out.println("合成图片完成：" + imageName);
    }

}
